#include<director.hpp>
namespace Engine{
    Director::Director(int width,int height,string title){
        // Load GLFW and Create a Window
        glfwInit();
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
        glfwWindowHint(GLFW_DECORATED, GL_FALSE);
        glfwWindowHint(GLFW_DEPTH_BITS, 32);
        glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
        glfwWindowHint(GLFW_SAMPLES, 4);
        m_window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);

        // Check for Valid Context
        if (m_window == nullptr)fprintf(stderr, "Failed to Create OpenGL Context");

        // Create Context and Load OpenGL Functions
        glfwMakeContextCurrent(m_window);
        gladLoadGL();
        fprintf(stderr, "OpenGL %s\n", glGetString(GL_VERSION));

        glfwSwapInterval(1);
        //glEnable(GL_CULL_FACE);
        //glEnable(GL_LIGHTING);
        //glEnable(GL_LIGHT0);
        glEnable(GL_DEPTH_TEST);
        //glEnable(GL_NORMALIZE);
        glEnable(GL_MULTISAMPLE);

        m_shader.init();
        m_shader.attach("resources/shader/model.vert").attach("resources/shader/model.frag");
        m_shader.link();
        m_shader.activate();
    }
    bool Director::ShouldClose(){
        return glfwWindowShouldClose(m_window);
    }
    Director::~Director(){
        glfwTerminate();
    }
    void Director::Update(){
        glfwSwapBuffers(m_window);
        glfwPollEvents();
    }
    void Director::Clear(){
        //glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
        //glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    }
    void Director::Render(){
        for(Node * i : m_nodes){
            i->Render();
        }
    }
    void Director::AddChild(Node *object){
        object->Setup(this->getShader());
        m_nodes.push_back(object);
    }
    Shader & Director::getShader(){
        return m_shader;
    }
}